package com.sduept.nwld.dataserver.controller.equipment.assessment.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.sduept.bigdata.equipment.assessment.exception.ParameterException;
import com.sduept.bigdata.equipment.assessment.model.inspection.InspectionExpert;
import com.sduept.bigdata.equipment.assessment.model.inspection.InspectionItem;
import com.sduept.bigdata.equipment.assessment.model.inspection.InspectionQuestionEquipment;
import com.sduept.bigdata.equipment.assessment.model.inspection.InspectionStation;
import com.sduept.bigdata.equipment.assessment.service.impl.DeductionTaskService;
import com.sduept.utils.CharacterUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 检查项目excel读取(easyexcel 工具）
 * @author lxj
 * @Date 2020年1月11日
 */
@Slf4j
public class InspectionItemExcelDataListener extends AnalysisEventListener<ExportInspectionItemDTO> {


	private DeductionTaskService deductService;
	
	private String inspectionStationId;
	/**
	 * Map<imageName,itemId>
	 */
	private Map<String,String> imageNameAndItemIdMap;
	
	private Map<String,InspectionExpert> expertMap;
	// 记录错误行信息
	private StringBuilder errorInfos = new StringBuilder();
	
	private List<ExportInspectionItemDTO> list = new ArrayList<>();
	public InspectionItemExcelDataListener(DeductionTaskService deductService,String inspectionStationId,Map<String,String> map, Map<String,InspectionExpert> expertMap,StringBuilder errorInfos) {
		super();
		this.deductService = deductService;
		this.inspectionStationId = inspectionStationId;
		this.imageNameAndItemIdMap = map;
		this.expertMap = expertMap;
		this.errorInfos = errorInfos;
	}
	
	/**
	 * 所有数据解析完成调用此方法
     *
     * @param context
     */
	@Override
	public void doAfterAllAnalysed(AnalysisContext context) {
		for (ExportInspectionItemDTO dto : list) {
			String inspectionCriterionNo = dto.getInspectionCriterionNo();
			if(StringUtils.isBlank(inspectionCriterionNo)) {
				// 如果对应表单规范序号为空，忽略
				if(0 != dto.getNo()) {
					errorInfos.append("第"+dto.getNo()+"行评价标准序号为空；");
//					errorInfos.append(System.getProperty("line.separator"));
				}
				continue;
			}
			InspectionItem item = deductService.getInspectionItemByNodeNo(inspectionStationId, inspectionCriterionNo);
			if(null == item) {
 				errorInfos.append("第"+dto.getNo()+"行找不到对应的评价标准；");
//				errorInfos.append(System.getProperty("line.separator"));
				continue;
			}
			if(StringUtils.isBlank(dto.getEquipmentBay())) {
				continue;
			}
			// item改变的扣分
			float newDeduct = 0;
			// item原有的问题间隔
			List<InspectionQuestionEquipment> originEquipments = item.getQuestionEquipments();
			Map<String,InspectionQuestionEquipment> map = new HashMap<String, InspectionQuestionEquipment>();
			
			for (InspectionQuestionEquipment inspectionQuestionEquipment : originEquipments) {
				map.put(inspectionQuestionEquipment.getEquipmentName(), inspectionQuestionEquipment);
			}
			List<ExportInspectionItemDTO> temps = splitMultipleEquipments(dto);
			for (ExportInspectionItemDTO temp : temps) {
				InspectionQuestionEquipment t = map.get(temp.getEquipmentBay());
				// TODO 如果是更新，是否要将问题设备原有问题图片删除 ？？？？
				if(null != t) {
					float oldDeduct = t.getQuesDeduct();
					// 更新操作
					try {
						Double f = Double.valueOf(temp.getQuestionAmount());
						int amount = (int)Math.floor(f);
						if(amount>0) {
							t.setQuestionAmount(amount);
						} else {
							t.setQuestionAmount(1);
						}
					} catch (Exception e) {
						// TODO: handle exception
						errorInfos.append("第"+dto.getNo()+"行问题设备有误；");
					}
					t.setRecommendation(temp.getRecommendation());
					t.setHiddenDangerDesc(temp.getProblemDescription());
					t.setQuesDeduct(t.getQuestionAmount()*item.getDeductionCriteria());
					t.setUpdateTime(System.currentTimeMillis());
					if(temp.getRiskLevel().contains("建议")) {
						t.setRiskLevel("建议级");
					} else {
						t.setRiskLevel(temp.getRiskLevel());
					}
					newDeduct = t.getQuesDeduct()-oldDeduct;
					if(StringUtils.isNotBlank(temp.getImageUrl())) {
						String[] images = temp.getImageUrl().split(",");
						for (String image : images) {
							imageNameAndItemIdMap.put(image, t.getId());
						}
					}
				} else {
					// 新增操作
					InspectionQuestionEquipment e = genEquipment(item, temp);
					if(StringUtils.isNotBlank(temp.getImageUrl())) {
						String[] images = temp.getImageUrl().split(",");
						for (String image : images) {
							imageNameAndItemIdMap.put(image, e.getId());
						}
					}
					originEquipments.add(e);
					newDeduct += e.getQuesDeduct();
				}
				
			}
			InspectionStation station = deductService.getInspectionStationById(inspectionStationId);
			station.setStatus(1);
			//评价专家不再设置多个，以第一个为主
			String expertName = dto.getInspectionExpert();
			item.setActualAssessmentExpertPhone(dto.getInspectionExpertPhone());
			if(StringUtils.isNotBlank(expertName)) {
				InspectionExpert expert = expertMap.get(expertName);
				if(null != expert) {
					item.setActualAssessmentExpertName(expertName);
					item.setActualAssessmentExpertId(expert.getId());
					if(StringUtils.isBlank(item.getActualAssessmentExpertPhone())) {
						item.setActualAssessmentExpertPhone(expert.getTelephone());
					}
				} else {
					item.setActualAssessmentExpertName(expertName);
				}
			} else {
				item.setActualAssessmentExpertName(station.getInspectionExpert());
				item.setActualAssessmentExpertId(station.getInspectionExpertId());
				item.setActualAssessmentExpertPhone(station.getInspectionExpertPhone());
			}
			if(dto.getRiskLevel().contains("建议")) {
				newDeduct = item.getRealDeduct();
			} else {
				newDeduct += item.getRealDeduct();
			}
			try {
				deductService.doDeduction(inspectionStationId, item.getId(),newDeduct);
			} catch (ParameterException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 当有多个问题设备时，将问题设备、问题数量、整改建议、问题描述、问题设备图片按照顺序进行匹配
	 * @param dto
	 * @return 
	 */
	private List<ExportInspectionItemDTO> splitMultipleEquipments(ExportInspectionItemDTO dto) {
		List<ExportInspectionItemDTO> results = new ArrayList<>();
		// [问题间隔1][问题间隔2][问题间隔3]
		String[] equipments = null;
		String eq = dto.getEquipmentBay();
		if(StringUtils.isBlank(eq)) {
			return new ArrayList<ExportInspectionItemDTO>();
		} else {
			equipments = splitString(eq);
		}
		// 问题数量
		String[] amounts = null;
		String qeamount = dto.getQuestionAmount();
		if(StringUtils.isNotBlank(qeamount)) {
			qeamount = CharacterUtil.qj2bj(qeamount);
			try {
				amounts = qeamount.split(",");
			} catch (Exception e) {
				errorInfos.append("第"+dto.getNo()+"行问题数量填写错误；");
//				errorInfos.append(System.getProperty("line.separator"));
			}
		}
		
		// 整改建议，格式：[第一部分][第二部分][第三部分]
		String[] recommendations = null;
		String recommendation = dto.getRecommendation();
		if(StringUtils.isNotBlank(recommendation)) {
			recommendations = splitString(recommendation);
		}
		
		// 问题描述，格式：[第一部分][第二部分][第三部分]，所有问题间隔是同一个描述的，可以写一条[]
		String[] descriptions = null;
		String desc = dto.getProblemDescription();
		if(StringUtils.isNotBlank(desc)) {
			descriptions = splitString(desc);
		}
		
		// 问题设备图片，格式：[图片1，图片2，图片3][图片a，图片b，图片c]
		String[] imageUrls = null;
		String imageUrl = dto.getImageUrl();
		if(StringUtils.isNotBlank(imageUrl)) {
			imageUrl = CharacterUtil.qj2bj(imageUrl);
			imageUrls = splitString(imageUrl);
		}
		
		for(int i=0; i<equipments.length; i++) {
			ExportInspectionItemDTO tmp = new ExportInspectionItemDTO();
			tmp.setNo(dto.getNo());
			tmp.setEquipmentBay(equipments[i]);
			if(null != amounts && amounts.length>i) {
				tmp.setQuestionAmount(amounts[i]);
			} else {
				tmp.setQuestionAmount("1");
			}
			if(null != recommendations && recommendations.length>i) {
				if(recommendations.length==1) {
					//只有一条建议时，默认所有间隔都是该建议
					tmp.setRecommendation(recommendations[0]);
				}else if(recommendations.length>i) {
					tmp.setRecommendation(recommendations[i]);
				}
			}
			if(null != descriptions) {
				if(descriptions.length==1) {
					//只有一条描述，默认所有间隔都是该描述
					tmp.setProblemDescription(descriptions[0]);
				}else if(descriptions.length>i) {
					tmp.setProblemDescription(descriptions[i]);
				}
			}
			if(null != imageUrls && imageUrls.length>i) {
				tmp.setImageUrl(imageUrls[i]);
			}
			tmp.setRiskLevel(dto.getRiskLevel());
			results.add(tmp);
		}
		return results;
	}
	
	private String[] splitString(String str) {
		List<String> strs2 = new ArrayList<String>();
		Pattern st2 = Pattern.compile("\\[(.*?)]");
		Matcher m = st2.matcher(str);
		boolean flag = false;
		while(m.find()){
			flag = true;
			strs2.add(m.group(1));
		}
		if(!flag) {
			strs2.add(str);
		}
		
		String[] result = strs2.toArray(new String[strs2.size()]);
		return result;
	}
	
	private InspectionQuestionEquipment genEquipment(InspectionItem item,ExportInspectionItemDTO dto) {
		InspectionQuestionEquipment eq = new InspectionQuestionEquipment();
		eq.init();
		eq.setEquipmentName(dto.getEquipmentBay());
		try {
			Double f = Double.valueOf(dto.getQuestionAmount());
			int amount = (int)Math.floor(f);
			if(amount>0) {
				eq.setQuestionAmount(amount);
			} else {
				eq.setQuestionAmount(1);
			}
		} catch (Exception e) {
			errorInfos.append("第"+dto.getNo()+"行问题设备数量填写错误；");
//			errorInfos.append(System.getProperty("line.separator"));
		}
		eq.setRecommendation(dto.getRecommendation());
		eq.setHiddenDangerDesc(dto.getProblemDescription());
		eq.setPlanId(item.getPlanId());
		eq.setInspectionStationId(inspectionStationId);
		InspectionStation is = deductService.getInspectionStationById(inspectionStationId);
		eq.setStationId(is.getStationId());
		eq.setStationName(is.getStationName());
		eq.setUpdateTime(System.currentTimeMillis());
		eq.setInspectionItem(item);
		eq.setQuesDeduct(eq.getQuestionAmount()*item.getDeductionCriteria());
		eq.setRiskLevel(dto.getRiskLevel());
		return eq;
	}


	/**
	 * 这个每一条数据解析调用此方法
     *
     * @param data
     *            one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
	@Override
	public void invoke(ExportInspectionItemDTO dto, AnalysisContext context) {
		list.add(dto);
	}
	
	@Override
	public void onException(Exception exception, AnalysisContext context) {
	    log.error("解析失败，继续解析下一行");
	    // 如果是某一个单元格的转换异常 能获取到具体行号
	    // 如果要获取头的信息 配合invokeHeadMap使用
	    if (exception instanceof ExcelDataConvertException) {
	        ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
	        int rowIndex = excelDataConvertException.getRowIndex()+1;
	        int colIndex = excelDataConvertException.getColumnIndex()+1;
	        errorInfos.append("第"+rowIndex+"行，第"+colIndex+"列解析异常；");
//	        errorInfos.append(System.getProperty("line.separator"));
//	        errorInfos.append("\r\n");
	        log.error("第"+rowIndex+"行，第"+colIndex+"列解析异常");
	    }
	}
}
